﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using XNAnimation;
//using XNAnimationPipeline;
using XNAnimation.Controllers;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XNAnimation.Effects;
using COC.GameLogic;

namespace COC.Graphics
{
	public class SingleCharacter
	{
		public Matrix LocalToWorld;
		public AnimationController AnimController;
	}

	public class AnimCharacter// : IRenderable
	{
		//internal Dictionary<string, Matrix> LocalToWorldMats = new Dictionary<string, Matrix>();
		//internal AnimationController AnimController = null;

		internal Dictionary<string, SingleCharacter> SingleCharacterInfo = new Dictionary<string, SingleCharacter>();

		internal SkinnedModel SkModel = null;
		internal Texture2D SpecularTexture = null;
		internal Texture2D NormalMap = null;
		internal bool EnableSpecularTexture = false;
		internal bool EnableNormalMap = false;

		public AnimCharacter(SkinnedModel model, Texture2D specular, Texture2D normal)
		{
			SkModel = model;
			EnableNormalMap = (normal == null);
			EnableSpecularTexture = (specular == null);
			SpecularTexture = specular;
			NormalMap = normal;
		}

		public void Render()
		{
			if (SingleCharacterInfo.Count < 1)
				return;

			foreach (ModelMesh modelMesh in SkModel.Model.Meshes)
			{
				foreach (ModelMeshPart meshPart in modelMesh.MeshParts)
				{
					SkinnedModelBasicEffect effect = meshPart.Effect as SkinnedModelBasicEffect;

					effect.View = CoCGame.Singleton.GameCamera.MatView;
					effect.Projection = CoCGame.Singleton.GameCamera.MatProj;

					//# FIXME #
					effect.Material.DiffuseColor = new Vector3(0.8f);
					effect.Material.SpecularColor = new Vector3(0.3f);
					effect.Material.SpecularPower = 8;

					effect.NormalMapEnabled = EnableNormalMap;

					effect.SpecularMapEnabled = EnableSpecularTexture;
					effect.SpecularMap = SpecularTexture;
					if (EnableSpecularTexture)
						effect.Material.SpecularColor = new Vector3(1.0f);

					// OPTIONAL - Configure lights
					effect.AmbientLightColor = new Vector3(0.3f);
					effect.LightEnabled = true;
					effect.EnabledLights = EnabledLights.One;
					effect.PointLights[0].Color = Vector3.One;
					effect.PointLights[0].Position = new Vector3(100, 100, 100);
				}

				foreach (SingleCharacter character in SingleCharacterInfo.Values)
				{
					foreach (ModelMeshPart meshPart in modelMesh.MeshParts)
					{
						SkinnedModelBasicEffect effect = meshPart.Effect as SkinnedModelBasicEffect;
						effect.World = character.LocalToWorld;
						effect.Bones = character.AnimController.SkinnedBoneTransforms;
					}
					modelMesh.Draw();
				}
			}
		}

		public void RenderDepth()
		{

		}
	}

	class AnimComponent : IRenderComponent
	{
		Dictionary<string, AnimCharacter> m_Actors = new Dictionary<string, AnimCharacter>();
		string[] m_ModelNames = new string[] { "PlayerMarine", "EnemyBeast", "WeaponMachineGun" };
		public AnimComponent()
		{

		}

		public SingleCharacter CreateInstance(string modelName, string instanceName,
			Vector3 spawn, Vector3 rotation, out SkinnedModel model)
		{
			model = null;
			if (!m_Actors.ContainsKey(modelName))
			{
				return null;
			}

			string str = instanceName;
			int i = 0;
			while (m_Actors[modelName].SingleCharacterInfo.ContainsKey(str))
			{
				str = instanceName + i.ToString();
				i++;
			}

			SingleCharacter character = new SingleCharacter();
			character.AnimController = new AnimationController(m_Actors[modelName].SkModel.SkeletonBones);
			character.LocalToWorld = Matrix.CreateTranslation(spawn) * Matrix.CreateFromYawPitchRoll(rotation.Y, rotation.X, rotation.Z);
			m_Actors[modelName].SingleCharacterInfo.Add(str, character);
			model = m_Actors[modelName].SkModel;
			return character;
		}

		public bool RemoveInstance(AnimActor actor)
		{
			m_Actors[actor.ModelName].SingleCharacterInfo.Remove(actor.Name);
			return true;
		}

		public override void Initialize()
		{
			foreach (string modelName in m_ModelNames)
			{
				try
				{
					SkinnedModel skModel = CoCGame.Singleton.Content.Load<SkinnedModel>(@"Models\" + modelName);

					Texture2D normal;
					try
					{
						normal = CoCGame.Singleton.Content.Load<Texture2D>(@"Textures\" + modelName + "Normal");
					}
					catch
					{
						normal = CoCGame.Singleton.Content.Load<Texture2D>(@"Textures\null_normal");
					}
					
					AnimCharacter ac = new AnimCharacter(skModel, null, normal);

					m_Actors.Add(modelName, ac);
				}
				catch (FileNotFoundException)
				{
					continue;
				}
			}
		}

		public override void Render()
		{
			foreach (AnimCharacter actor in m_Actors.Values)
			{
				actor.Render();
			}
		}

		public override void Dispose()
		{
			
		}
	}
}